# -*- coding: utf-8 -*-
"""
Macana XML-RPC Dispatcher for Taíno
Copyright (C) 2009, Joshua "jag" Ginsberg <jag@flowtheory.net

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
"""

import pydoc
import xmlrpclib
from django.test import TestCase
from django.http import HttpRequest
from django.conf import settings as site_settings
from django.contrib.auth.models import User
from taino import models
from taino.api import Component
from macana.api import IMacanaXMLRPCMethod, IMacanaAuthentication
from macana import dispatcher

class SystemAuthRequired(Component):
    implements = IMacanaXMLRPCMethod
    component_id = 'net.skwx.macana.SystemAuthRequired'
    component_description = 'Tests authentication credentials'
    
    def get_method_name(self):
        return u'system.authRequired'
    
    def get_arg_list(self):
        return []
    
    def get_return_type(self):
        return 'boolean'
    
    def authorize(self, request):
        return hasattr(request, 'user') and isinstance(request.user, User)
    
    def handle_request(self, request):
        return True

class SystemListMethodsTest(TestCase):
    
    def setUp(self):
        self.component = IMacanaXMLRPCMethod.get_component_by_id("net.skwx.macana.SystemListMethods")
        
    def test_simple_functions(self):
        self.assertEqual("system.listMethods", 
                         self.component.get_method_name())
        self.assertEqual([],
                         self.component.get_arg_list())
        self.assertEqual('array',
                         self.component.get_return_type())
        self.assert_(self.component.authorize(HttpRequest()))
    
    def test_handle_request(self):
        results = self.component.handle_request(HttpRequest())
        self.assert_('system.listMethods' in results)
        self.assert_('system.methodSignature' in results)
        self.assert_('system.methodHelp' in results)
    
class SystemMethodSignatureTest(TestCase):
    def setUp(self):
        self.component = IMacanaXMLRPCMethod.get_component_by_id("net.skwx.macana.SystemMethodSignature")
        
    def test_simple_functions(self):
        self.assertEqual("system.methodSignature", 
                         self.component.get_method_name())
        self.assertEqual(['string'],
                         self.component.get_arg_list())
        self.assertEqual('array',
                         self.component.get_return_type())
        self.assert_(self.component.authorize(HttpRequest()))
    
    def test_handle_request(self):
        self.assertEqual(self.component.handle_request(HttpRequest(),
                                                       'system.listMethods'),
                         [])
        self.assertEqual(self.component.handle_request(HttpRequest(),
                                                       'system.methodSignature'),
                         ['string'])
        self.assertEqual(self.component.handle_request(HttpRequest(),
                                                       'system.methodHelp'),
                         ['string'])
    

class SystemMethodHelpTest(TestCase):
    def setUp(self):
        self.component = IMacanaXMLRPCMethod.get_component_by_id("net.skwx.macana.SystemMethodHelp")
        
    def test_simple_functions(self):
        self.assertEqual("system.methodHelp", 
                         self.component.get_method_name())
        self.assertEqual(['string'],
                         self.component.get_arg_list())
        self.assertEqual('string',
                         self.component.get_return_type())
        self.assert_(self.component.authorize(HttpRequest()))
    
    def test_handle_request(self):
        self.assertEqual(self.component.handle_request(HttpRequest(),
                                                       'system.methodHelp'),
                         pydoc.getdoc(self.component.handle_request))
    
class DispatcherTest(TestCase):
    def setUp(self):
        self.dispatcher = dispatcher.MacanaXMLRPCDispatcher(
            IMacanaAuthentication, IMacanaXMLRPCMethod
            )
        self.test_user = User.objects.create_user('jpschmoe',
                                                  'joeschmoe@example.com',
                                                  'foopass')
    
    def test_no_auth_correct_method(self):
        site_settings.MACANA_AUTH_COMPONENT = 'net.skwx.macana.NoAuthentication'
        self.dispatcher._load_authentication_component()

        results = self.dispatcher._dispatch(
            HttpRequest(),
            'system.listMethods',
            [])
        self.assert_('system.listMethods' in results)
        self.assert_('system.methodSignature' in results)
        self.assert_('system.methodHelp' in results)
        
    def test_no_auth_incorrect_method(self):
        site_settings.MACANA_AUTH_COMPONENT = 'net.skwx.macana.NoAuthentication'
        self.dispatcher._load_authentication_component()
        self.assertRaises(xmlrpclib.Fault,
                          self.dispatcher._dispatch,
                          HttpRequest(),
                          'system.nonExistentMethod',
                          [])
    
    def test_basic_auth(self):
        site_settings.MACANA_AUTH_COMPONENT = 'net.skwx.macana.HttpBasicAuth'
        self.dispatcher._load_authentication_component()
        
        req = HttpRequest()
        req.META['HTTP_AUTHORIZATION'] = "Basic anBzY2htb2U6Zm9vcGFzcw=="
        
        self.assert_(self.dispatcher._dispatch(
            req,
            'system.authRequired',
            []))
        
    def test_bad_basic_auth(self):
        site_settings.MACANA_AUTH_COMPONENT = 'net.skwx.macana.HttpBasicAuth'
        self.dispatcher._load_authentication_component()
        
        req = HttpRequest()
        req.META['HTTP_AUTHORIZATION'] = "Basic anBzY2htb2U6YmFkcGFzcw=="
        
        self.assertRaises(
            xmlrpclib.Fault,
            self.dispatcher._dispatch,
            req,
            'system.authRequired',
            [])
    
    def test_no_basic_auth(self):
        site_settings.MACANA_AUTH_COMPONENT = 'net.skwx.macana.HttpBasicAuth'
        self.dispatcher._load_authentication_component()
        
        req = HttpRequest()
        
        self.assertRaises(
            xmlrpclib.Fault,
            self.dispatcher._dispatch,
            req,
            'system.authRequired',
            [])
